package flca.voicenav.model;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import android.util.Log;

import com.google.android.maps.GeoPoint;

import flca.voicenav.VoiceNavConstants;

public class GpxRoute implements Serializable, VoiceNavConstants
{
	private static final long serialVersionUID = 740773497743462130L;

	private String name;
	private List<TrkPt> coordinates = new ArrayList<TrkPt>();
	private double minLat, maxLat, minLng, maxLng;
	double totalDistance;
	boolean closed;
	
	public String getName()
	{
		return name;
	}
	public void setName(String name)
	{
		this.name = name;
	}
	public List<TrkPt> getCoordinates()
	{
		return coordinates;
	}
	public void setCoordinates(List<TrkPt> coordinates)
	{
		this.coordinates = coordinates;
	}
	public double getMinLat()
	{
		return minLat;
	}
	public void setMinLat(double minLat)
	{
		this.minLat = minLat;
	}
	public double getMaxLat()
	{
		return maxLat;
	}
	public void setMaxLat(double maxLat)
	{
		this.maxLat = maxLat;
	}
	public double getMinLng()
	{
		return minLng;
	}
	public void setMinLng(double minLng)
	{
		this.minLng = minLng;
	}
	public double getMaxLng()
	{
		return maxLng;
	}
	public void setMaxLng(double maxLng)
	{
		this.maxLng = maxLng;
	}
	public double getTotalDistance()
	{
		return totalDistance;
	}
	public void setTotalDistance(double distance)
	{
		this.totalDistance = distance;
	}
	
	public boolean isClosed() {
		return closed;
	}
	public void setClosed(boolean closed) {
		this.closed = closed;
	}
	//------- extra ----
	public int size() {
		return getCoordinates().size();
	}
	
	public TrkPt getTrkPt(int aIndex) {
		return getCoordinates().get(aIndex);
	}

	public GeoPoint getPoint(int aIndex) {
		return getTrkPt(aIndex).toGeoPoint();
	}
	
	public GeoPoint[] getSegmentPoints(int aIndex) 
	{
		GeoPoint r[] = new GeoPoint[2];
		
		r[0] = getPoint(aIndex);
		
		if (aIndex == size() - 1) {
			r[1] = isClosed() ? getPoint(0) : r[0];
		} else {
			r[1] = getPoint(aIndex + 1);
		}
		
		return r;
	}
	
	/** 
	 * return the next index. Normally this is just the next of prev depending on dir,
	 * but it will also take into account if is a closed route. In that case we give for the next (or prev) on the other side
	 * otherwise we return -1
	 * @param aFromIndex
	 * @return
	 */
	public int getNextIndex(int aFromIndex, Dir aDir)
	{
		if (Dir.DOWN.equals(aDir)) {
			if (aFromIndex > 1) {
				return aFromIndex - 1;
			} else {
				return isClosed() ? size() -1 : -1;
			}
		} else {
			if (aFromIndex < size() - 2) {
				return aFromIndex + 1;
			} else {
				return isClosed() ? 0 : -1;
			}
		}
	}
	
	public int getNextCorner(int aSegmIndex)
	{
		int nc = getTheNextCorner(aSegmIndex);
		int pc = getThePrevCorner(aSegmIndex);
		if (nc == pc) {
			Log.e(TAG, "next & prev corner zijn gelijk!");
		}
		return nc;
	}

	public int getPrevCorner(int aSegmIndex)
	{
		int nc = getTheNextCorner(aSegmIndex);
		int pc = getThePrevCorner(aSegmIndex);
		if (nc == pc) {
			Log.e(TAG, "next & prev corner zijn gelijk!");
		}
		return pc;
	}

	public int lastCorner() {
		return getTrkPt(size() - 1).getIndex();
	}
	public int firstCorner() {
		return getTrkPt(0).getIndex();
	}
	
	/**
	 * returns the index of the next (UP) corner.
	 * @param aSegmIndex
	 * @return
	 */
	private int getTheNextCorner(int aSegmIndex) 
	{
		if (aSegmIndex < size()) {
			for (int i=aSegmIndex + 1; i < size(); i++) {
				TrkPt trkpt = getTrkPt(i);
				if (trkpt.isCorner()) {
					return i;
				}
			}
			return size() - 1;
		} else {
			return size() - 1;
		}
	}

	/**
	 * returns the index of the nprev (DOWN) corner.
	 * @param aSegmIndex
	 * @return
	 */
	private int getThePrevCorner(int aSegmIndex) 
	{
		if (aSegmIndex > 0) {
			for (int i=aSegmIndex; i >= 0; i--) {
				TrkPt trkpt = getTrkPt(i);
				if (trkpt.isCorner()) {
					return i;
				}
			}
			return 0;
		} else {
			return 0;
		}
	}
}
